<template>
  <div
    v-if="!initializing"
    v-resize="resize"
    class="vc-component"
    :style="visual.parseStyle(currNode.currStyle)"
  >
    <div ref="chartDiv" class="vc-echarts-map" :style="style"></div>
  </div>
  <div
    v-else
    v-loading="true"
    element-loading-text=""
    style="min-height: 30px;"
    class="vc-component"
    :style="visual.parseStyle(currNode.currStyle)"
  ></div>
</template>

<script setup>
import { ref, onMounted, computed, inject, getCurrentInstance, markRaw, nextTick, onUnmounted } from 'vue';
import * as echarts from "echarts";
import visual from "@/visual/js/visual";
import EventHandler from "@/visual/js/event";
import * as chart from "@/visual/js/echarts";
import JSON5 from 'json5';
import { parseColors } from "@/utils/color";
import tool from "@/utils/tool";
import api from "@/http/api";

const props = defineProps({
  node: Object
});

const chartDiv = ref();
const currChart = ref(null);
const initializing = ref(true);
const currNode = ref(props.node);
const eventHandler = new EventHandler(
  inject('eventHandler', Function, true),
  getCurrentInstance(),
  currNode.value
);

const init = async(styleId) => {
  initializing.value = true;
  visual.initStyle(currNode.value, styleId);
  await nextTick(() => initializing.value = false);
};

const loadData = tool.debounce(async() => {
  if (!chartDiv.value) return;
  const compStyle = currNode.value.currCompStyle || {};
  const compData = currNode.value.compData || {};
  const defaultOption = JSON5.parse(compStyle['jsonOption'] || '{}');
  const dataList = (await visual.loadData(
    compData,
    eventHandler,
    getData(),
    currNode.value)).data || [];

  const mapIds = (compStyle['geo.mapId'] || '156').split(',');
  const mapId = mapIds[mapIds.length - 1];

  const seriesData = [];
  (compStyle.seriesList || []).forEach(item => {
    seriesData.push({
      type: item.type,
      name: item.name,
      geoIndex: 0,
      coordinateSystem: item.type !== 'map' ? 'geo' : null,
      data: dataList[0]?.[item.prop]
    });
  });

  const option = {
    geo: parseGeo(compStyle, mapId),
    visualMap: parseVisualMap(compStyle),
    animation: compStyle['animation'] || false,
    color: parseColors(compStyle['colorScheme']),
    title: chart.parseTitle(compStyle),
    tooltip: chart.parseTooltip(compStyle),
    series: seriesData,
    toolbox: chart.parseToolbox(compStyle)
  };

  await nextTick(async() => {
    const json = await api.get(`/assets/map/${mapId}.json`, false);
    echarts.registerMap(mapId, json.data);
    currChart.value = markRaw(echarts.init(chartDiv.value));
    currChart.value.setOption(Object.assign({}, option, defaultOption));
    currChart.value.on('click', 'series', function(params) {
      const data = {
        '系列名': params.name,
        '系列值': params.value
      };
      eventHandler.trigger("点击数据项事件", data);
    });
  });
  resize();
});

const parseGeo = (compStyle, mapId) => {
  const result = { map: mapId, roam: true };

  result['label'] = {
    show: !!compStyle['geo.label'],
    position: compStyle['geo.label.position'] || 'inside',
    distance: compStyle['geo.label.distance'] || 5,
    formatter: compStyle['geo.label.formatter'] || '',
    color: compStyle['geo.label.color'] || '#fff',
    fontSize: compStyle['geo.label.fontSize'] || 12,
  };

  result['itemStyle'] = {
    areaColor: compStyle['geo.itemStyle.areaColor'] || '#eee',
    color: compStyle['geo.itemStyle.color'] || null,
    borderColor: compStyle['geo.itemStyle.borderColor'] || '#000',
    borderWidth: compStyle['geo.itemStyle.borderWidth'] || 0,
    borderType: compStyle['geo.itemStyle.borderType'] || 'solid',
  }

  result['emphasis'] = {
    itemStyle: {
      areaColor: compStyle['geo.itemStyle.activeColor']
    }
  }

  result['select'] = {
    itemStyle: {
      areaColor: compStyle['geo.itemStyle.activeColor']
    }
  }

  return result;
};

const parseVisualMap = (compStyle) => {
  const resultList = [];

  (compStyle['visualMapList'] || []).forEach(item => {
    const result = {};
    result['show'] = !!item['show'];
    result['seriesIndex'] = item['seriesIndex'] || 0;
    result['calculable'] = true;
    result['type'] = item['type'] || 'continuous';
    result['min'] = item['min'] || null;
    result['max'] = item['max'] || null;
    result['orient'] = item['orient'] || 'horizontal';
    result['text'] = item['text'] ? item['text'].split(',') : null;
    result['dimension'] = item['dimension'] || null;

    result['inRange'] = {};
    if (item['inRange.symbol']) {
      result['inRange'].symbol = item['inRange.symbol'] || 'pin';
    }
    if (item['inRange.symbolSize']) {
      result['inRange'].symbolSize = item['inRange.symbolSize'].split(',');
    }
    if (item['inRange.color']) {
      result['inRange'].color = item['inRange.color'].split(',');
    }

    resultList.push(result);
  });

  return resultList;
};

const style = computed(() => {
  const compStyle = currNode.value.currCompStyle || {};

  let result = '';
  result += visual.parseTpl('width: {value};', compStyle['width']);
  result += visual.parseTpl('height: {value};', compStyle['height']);
  return result;
});

const getData = () => {
  return { inputParam: currNode.value.inputParam || {} };
};

const changeStyle = (styleId) => {
  init(styleId);
};

const refresh = async() => {
  await init();
  loadData();
};

const resize = () => {
  try {
    currChart.value.resize();
  } catch (e) {
    console.log(e);
  }
};

onMounted(async() => {
  await init();
  loadData();
});

onUnmounted(() => {
  eventHandler.unregister();
});

defineExpose({ getData, changeStyle, refresh, loadData });
</script>